package com.lwhtarena.netty.netty4.server;

import com.lwhtarena.netty.netty4.model.RequestFile;
import com.lwhtarena.netty.netty4.model.ResponseFile;
import com.lwhtarena.netty.netty4.util.FileInfo;
import com.lwhtarena.netty.netty4.util.FileInfoBuilder;
import com.lwhtarena.netty.netty4.util.FileTransferProperties;
import com.lwhtarena.netty.netty4.util.MD5FileUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.CharsetUtil;
import io.netty.util.internal.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Date;
import java.util.Iterator;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;

public class SampleFileHandler extends SimpleChannelInboundHandler<ByteBuf> {

    private static final Logger log = LoggerFactory.getLogger(FileTransferServerHandler.class);

    /**
     * 文件默认存储地址
     */
    private String file_dir = FileTransferProperties.getString("file_write_path", "/");


    private static int sort = 0;
    private static int loop = 0;

    private static ConcurrentHashMap<String,FileInfo> fileMap = new ConcurrentHashMap<String, FileInfo>();
    private static ConcurrentHashMap<String, LinkedBlockingQueue<byte[]>> fileBlockMap = new ConcurrentHashMap();

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception {
        sort = sort+1;

        int len = byteBuf.readableBytes();
        //log.debug("字节长度{}", len);
        System.out.println("第"+sort+"次接收"+ctx.channel().remoteAddress()+"字节长度"+len);
        String s = byteBuf.toString(CharsetUtil.US_ASCII);
        FileInfo sourceFile = FileInfoBuilder.convertFile(s);
        byte[] bytes = new byte[len];
        byteBuf.readBytes(bytes);
        if (sourceFile!= null) {
            sourceFile.setRandomAccessFile("E:\\TEMP\\netty-temp"+File.separator+sourceFile.getFilename());
            fileMap.put("file",sourceFile);
            System.out.println("文件名："+sourceFile.getFilename());
            System.out.println("文件格式："+sourceFile.getFileFormat());
            System.out.println("文件大小："+sourceFile.getFilesize());
            return;
        } else {
            LinkedBlockingQueue<byte[]> queue = fileBlockMap.get(ctx.channel().remoteAddress().toString());
            if (queue == null ){
                LinkedBlockingQueue blockingQueue = new LinkedBlockingQueue();
                blockingQueue.put(bytes);
                fileBlockMap.put(ctx.channel().remoteAddress().toString(),blockingQueue);
            } else {
                queue.put(bytes);
            }
        }



        if (fileMap.get("file") != null) {
            FileInfo fileInfo = fileMap.get("file");
            fileMap.put(ctx.channel().remoteAddress().toString(),fileInfo);
            fileMap.remove("file");

        }


    }





    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();

        if (fileMap.get(ctx.channel().remoteAddress().toString()) != null) {
            FileInfo fileInfo = fileMap.get(ctx.channel().remoteAddress().toString());
           try {
                fileInfo.getRandomAccessFile().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
           fileMap.remove(ctx.channel().remoteAddress().toString());
        }
        System.out.println(ctx.channel().remoteAddress() + "连接异常");
        ctx.close();
    }



    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception{
        System.out.println(ctx.channel().remoteAddress()+"接收阅读完成");
    }

    public void channelInactive(ChannelHandlerContext ctx) throws Exception{
        sort = 0;
        System.out.println(ctx.channel().remoteAddress()+"连接已断开");
        FileInfo fileInfo = fileMap.get(ctx.channel().remoteAddress().toString());
        LinkedBlockingQueue<byte[]> queue = fileBlockMap.get(ctx.channel().remoteAddress().toString());
        if (fileInfo!=null){
            while (queue!=null&&!queue.isEmpty()){
                byte[] poll = queue.poll();
                fileInfo.getRandomAccessFile().write(poll);
                System.out.println(ctx.channel().remoteAddress()+"文件指针位置："+fileInfo.getRandomAccessFile().getFilePointer()+"总文件大小："+fileInfo.getFilesize()+"文件名: "+fileInfo.getFilename());
            }
            fileInfo.getRandomAccessFile().getFD().sync();
            fileInfo.getRandomAccessFile().close();
            fileMap.remove(ctx.channel().remoteAddress().toString());
            fileBlockMap.remove(ctx.channel().remoteAddress().toString());
        }


    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        loop = loop + 1;
        System.out.println(ctx.channel().remoteAddress()+"连接成功"+loop+"次");
    }


}
